#include <string>
#include <iostream>

using namespace std;

#define TRACESIZE(object) cout << sizeof(object) << endl;
#define TRACE(bs) cout << bs << endl;

// class defaults to private
// struct defaults to public
// only difference.. ONLY
class Person
{
public:
	char *firstName;
	char *lastName;
	Person()
	{ cout << "Person Constructor invoked" << endl; }
	~Person()
	{ cout << "Person Destructor invoked" << endl; }

};

class IntHolder
{
public:
	int currentValue;
	IntHolder(int value)
	{
		currentValue = value;
		cout << currentValue << endl;
	}
	~IntHolder()
	{
		cout << currentValue << endl;
	}
};


class Base
{
public:
	int member;
	Base()
	{
		cout << "Base constructor" << endl;
	}
	~Base()
	{
		cout << "Base destructor" << endl;
	}
	virtual void moo(){ TRACE("Base::moo()"); }
};

class Derived : public Base
{
public:
	Derived()
	{
		cout << "Derived constructor" << endl;
	}
	~Derived()
	{
		cout << "Derived destructor" << endl;
	}
	void moo(){ TRACE("Derived::moo"); }
};

/*
* Wrestle part 1
*Make a class
**/
void Part1()
{
	// Part 1
	// declared on stack
	// this is not NULL
	Person person1;
	person1.firstName = "Steve";
	person1.lastName = "Stevenson";

	
	Person person2;
	person2.firstName = "John";
	person2.lastName = "Johnson";
	
	cout << person1.firstName << " " << person1.lastName << endl;
	cout << person2.firstName << " " << person2.lastName << endl;
}

/**
* Wrestle part 2
* Construction, Destruction, and defining data on the stack
*
*
**/
void Part2()
{
	cout << "Outermost scope begin" << endl;

	/**
	* Prints outerBS 123321 outerBS
	* This is because when a type is made on the stack, 
	* it is constructed when declared and destructed when 
	* the executing thread leaves the declared variable's 
	* scope.
	**/
	Outer:
	{
		IntHolder holder(1);

		Middle:
		{
			IntHolder holderMidScope(2);

			Inner:
			{
				IntHolder holderLowerScope(3);
			}
		}

	}
	cout << "Outermost scope end" << endl;

	cout << sizeof(IntHolder) << endl;
}

/**
* Wrestle part 5
* Inheritance and constructor execution order
**/
void Part5()
{
	/**
	* Base constructor is called first, 
	* followed by the derived constructor.
	*
	* This happens because the base type must be initialized for the
	* derived type so the derived constructor can use the base type's data.
	* The destructor invocation order is opposite for a similar but opposite reason,
	* the base type's data must be intact because the derived type needs it. Also, these 
	* print orders occur in a stack-like order.
	**/
	Derived derived;
}

/**
* Wrestle part 6
* vPointers
**/
void Part6()
{
	/**
	* When a type is traced without any virtual methods, 
	* the size is equal to the combined size of its members.
	*
	* Once a virtual method is added, the size increases by 4 bytes.
	* This happens because the only way to support overridable methods is
	* to replace it with a pointer to the segment of code that is executed in the
	* method's place.
	**/
	TRACESIZE(Base);
	TRACESIZE(Derived);
}

/**
*What is a class?
*	A blueprint or framework describing the members and functionality for a type of objects.
* 
*What differences exist between a class and an object?
*	An object is an instance of a class while a class is the definition of a group (classification) of objects
* 
*What is the difference between a class and a struct?
*	In c++, a class defaults to private while a struct defaults to public for members without an explicit scope modifier
* 
*What is inheritance?
*	The ability of a derived class to adopt the functionality and structure of a "base" or parent class at compile time.
*
*What differences exist between a base class and a derived class?
* 
*
*When should you use multiple inheritance?
*	You shouldn't, but if you really insist on doing so I would only use it when I need 
* 
*What is polymorphism?
*	Polymorphism is the ability of a derived class to masquerade as one of its base typeswhile maintaining its functionality
* 
*Why use the virtual keyword instead of a switch structure?
*	Because the code actually makes sense this way.
* 
*What is a vTable?
*	A table of pointers to overriden virtual methods
* 
*What does adding the virtual keyword do to that class?
*	it adds a vTable to the class when it is compiled. It also increases the size by
*	4 bytes per virtual method.
**/
void main()
{
	//Part1();
	//Part2();
	//Part5();
	//Part6();
}